package elevator

import (
	"fmt"
	"sync"
	"time"
)

type Elevator struct {
	currentLayers int8 		//电梯当前层数
	maxLayers int8 			//电梯最大层数
	minLayers int8 			//电梯最小层数
	runningDirection int8 	//运行方向 1向上 -1向下 0静止状态
	upFloorQueue []int8 	//向上目标楼层队列
	downFloorQueue []int8 	//向下楼层队列
	RWLock sync.RWMutex
	wg *sync.WaitGroup
}

func CreateElevator(maxLayers,minLayers int8,wg *sync.WaitGroup) Elevator {
	return Elevator{
		maxLayers:maxLayers,
		minLayers: minLayers,
		currentLayers: int8(1),
		runningDirection: int8(0),
		wg: wg,
	}
}

func (e *Elevator) Run() {
	if e.runningDirection != 0{
		return
	}
	if len(e.upFloorQueue) != 0{
		e.runningDirection = 1
		e.UpRun()
	}else if len(e.downFloorQueue) != 0 {
		e.runningDirection = -1
		e.DownRun()
	}
}

func (e *Elevator) UpRun()  {
	for i:=e.currentLayers;len(e.upFloorQueue) > 0;i++{
		e.RWLock.RLock()
		fmt.Printf("显示屏：---当前层数--- %d\n",i)
		e.currentLayers = i
		time.Sleep(time.Second * 1)
		if i == e.upFloorQueue[0] {
			fmt.Printf("电梯停靠： %d\n",i)
			time.Sleep(time.Second * 2)
			e.upFloorQueue = e.upFloorQueue[1:]
			e.wg.Done()
		}
		e.RWLock.RUnlock()
	}
	fmt.Println("-------电梯向上运行结束------")
	e.runningDirection = 0
	e.Run()
}

func (e *Elevator) DownRun()  {
	for i:=e.currentLayers;len(e.downFloorQueue) > 0;i--{
		e.RWLock.RLock()
		fmt.Printf("显示屏：---当前层数--- %d\n",i)
		e.currentLayers = i
		time.Sleep(time.Second * 1)
		if i == e.downFloorQueue[len(e.downFloorQueue)-1] {
			fmt.Printf("电梯停靠： %d\n",i)
			time.Sleep(time.Second * 2)
			e.downFloorQueue = e.downFloorQueue[:len(e.downFloorQueue)-1]
			e.wg.Done()
		}
		e.RWLock.RUnlock()
	}
	fmt.Println("-------电梯向下运行结束------")
	e.runningDirection = 0
	e.Run()
}


// FloorClick 从楼层点击
func (e *Elevator) FloorClick(layers int8)  {
	//此处应该检测输入值是否已在两个队列之中
	if e.runningDirection == 1 && isContain(e.upFloorQueue,layers){
		return
	}
	if e.runningDirection == 0 && isContain(e.downFloorQueue,layers){
		return
	}
	e.RWLock.Lock()
	if layers > e.currentLayers{
		//此处实现插入排序
		e.upFloorQueue = insertSort(e.upFloorQueue,layers)
		fmt.Printf("---向上队列接收到楼层%d---\n",layers)
	}else {
		//bug 需要逆序排序
		e.downFloorQueue = insertSort(e.downFloorQueue,layers)
		fmt.Printf("---向下队列接收到楼层%d---\n",layers)
	}
	e.RWLock.Unlock()
	e.Run()
}

//插入排序
func insertSort(queue []int8,num int8) []int8 {
	left := 0
	right := len(queue) - 1
	for left <= right{
		mid := (left + right) >> 1
		if queue[mid] > num{
			right = mid - 1
		}else if queue[mid] < num{
			left = mid + 1
		}else {//相等证明已在队列，无需插入
			return queue
		}
	}
	//二分法未找到的话应该是left位置就是要插入的地方
	queue = append(queue,0)
	for i := len(queue)-1;i > left;i--{
		queue[i] = queue[i-1]
	}
	queue[left] = num
	return queue
}

//判断元素是否存在数组中
func isContain(items []int8, item int8) bool {
	for _, eachItem := range items {
		if eachItem == item {
			return true
		}
	}
	return false
}

